//
//  WNLoginVC.swift
//  WalkNovel
//
//  Created by Kevin on 2023/7/4.
//

import UIKit
import HandyJSON
import RxSwift
import RxCocoa
import KeychainAccess
import AuthenticationServices
import GoogleSignIn
import FBSDKLoginKit

class WNLoginVC: WNBaseVC {
    
    lazy var logoBg: UIImageView = {
        let image = UIImageView(image: UIImage(named: "logo_bg"))
        image.contentMode = .scaleAspectFill
        return image
    }()

    lazy var closeBtn: UIButton = {
        let btn = UIButton(type: .custom)
        btn.setImage(UIImage.init(named: "login_close"), for: .normal)
        btn.rx.tap.bind { [weak self] in
            self?.dismiss(animated: true, completion: {
                self?.disClosure?()
            })
        }.disposed(by: rx.disposeBag)
        return btn
    }()
    
    lazy var logoImage: UIImageView = {
        let image = UIImageView(image: UIImage(named: "login_logo"))
        image.wn_cornerWithBorder(8)
        return image
    }()
    
    lazy var appName: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = .init(named: "red_FE6390")
        label.font = .init(name: "PingFangSC-Medium", size: 24)
        label.text = "最嗨小说"
        return label
    }()
    
    lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = .init(named: "gray_666666")
        label.font = .wn_font(name: .bold, size: 18)
        label.text = "遇見你的下一本最喜歡的書"
        return label
    }()
    
    lazy var tipsLabel: UILabel = {
        let label = UILabel()
        label.textColor = .init(named: "gray_999999")
        label.font = .wn_font(name: .regular, size: 12)
        label.text = "您目前是訪客帳戶。為了保護您的帳戶安全，避免閱讀記錄遺失。請登入以繼續閱讀。登入後，您的訪客帳戶將與您的登入帳戶合併，利益和權利將被保留。"
        label.numberOfLines = 0
        return label
    }()

    lazy var agreeBtn: UIButton = {
        var btn = UIButton(type: .custom)
        btn.setImage(UIImage(named: "setting_feedback_chose_gray"), for: .normal)
        btn.setImage(UIImage(named: "setting_select"), for: .selected)
        btn.imageEdgeInsets = .init(top: 3, left: 3, bottom: 3, right: 3)
        btn.isSelected = true
        btn.rx.tap.bind { [weak self] in
            btn.isSelected = !btn.isSelected
        }.disposed(by: rx.disposeBag)
        return btn
    }()
    
    lazy var privacyView: IQTextView = {
        let view = IQTextView()
        view.font = .wn_font(name: .bold, size: 12)
        view.showsVerticalScrollIndicator = false
        view.wn_appendLinkString(string: "如果您繼續，即表示您同意")
        view.wn_appendLinkString(string: "《服務協議》", withURLString: WNConfigure.WNURL.wn_Agreement)
        view.wn_appendLinkString(string: "和")
        view.wn_appendLinkString(string: "《隱私政策》", withURLString: WNConfigure.WNURL.wn_Privacy)
        view.textColor = .init(named: "gray_999999")
        view.linkTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.init(named: "gray_666666")!]
        view.isEditable = false
        view.delegate = self
        view.contentInset = .init(top: -10, left: 0, bottom: 0, right: 0)
        return view
    }()
    
    lazy var appleBtn: UIButton = {
        let btn = UIButton(type: .custom)
        btn.setTitle(" 使用Apple登入", for: .normal)
        btn.titleLabel?.font = .wn_font(name: .bold, size: 16)
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel?.textAlignment = .center
        btn.rx.tap.bind { [weak self] in
            self?.touchAppleBtn()
        }.disposed(by: rx.disposeBag)
        btn.backgroundColor = WNColor.Fade().left2right(.init(width: scaleWidth(240), height: 44))
        btn.wn_cornerWithBorder(22)
        return btn
    }()
    
    lazy var fbBtn: UIButton = {
        let btn = UIButton.init(type: .custom)
        btn.setImage(UIImage(named: "login_facebook"), for: .normal)
        btn.rx.tap.bind { [weak self] in
            self?.touchFacebookBtn()
        }.disposed(by: rx.disposeBag)
//        btn.isHidden = true
        return btn
    }()
    
    lazy var goBtn: UIButton = {
        let btn = UIButton.init(type: .custom)
        btn.setImage(UIImage(named: "login_google"), for: .normal)
        btn.rx.tap.bind { [weak self] in
            self?.touchGoogleBtn()
        }.disposed(by: rx.disposeBag)
        btn.isHidden = true
        return btn
    }()
    
    lazy var lineView: UIView = {
        let view = UIView()
        view.backgroundColor = .white
        return view
    }()
    
    var disClosure: ReturnClosure?
        
    var emailStr = ""
    
    var verStr = ""
    
    var pwStr = ""
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        WNHUD.wn_hide()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewConfig() {
        wn_hidNavView()
        view.addSubview(logoBg)
        view.addSubview(closeBtn)
        view.addSubview(logoImage)
        view.addSubview(appName)
        view.addSubview(titleLabel)
        view.addSubview(tipsLabel)
        
        view.addSubview(agreeBtn)
        view.addSubview(privacyView)
        view.addSubview(lineView)
        view.addSubview(appleBtn)
        view.addSubview(fbBtn)
        view.addSubview(goBtn)
        
        logoBg.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        closeBtn.snp.makeConstraints { make in
            make.top.equalTo(StatusBarHeight)
            make.left.equalTo(12)
            make.width.height.equalTo(32)
        }
        logoImage.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(StatusBarHeight+84)
            make.width.height.equalTo(64)
        }
        appName.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(logoImage.snp.bottom).offset(16)
            make.height.equalTo(29)
        }
        titleLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(appName.snp.bottom).offset(10)
            make.height.equalTo(25)
        }
        tipsLabel.snp.makeConstraints { make in
            make.left.equalTo(22)
            make.right.equalTo(-22)
            make.top.equalTo(titleLabel.snp.bottom).offset(22)
        }
        agreeBtn.snp.makeConstraints { make in
            make.left.equalTo(18)
            make.bottom.equalTo(-48-TabBarMargin)
            make.width.height.equalTo(20)
        }
        privacyView.snp.makeConstraints { make in
            make.top.equalTo(agreeBtn.snp.top).offset(3)
            make.left.equalTo(agreeBtn.snp.right).offset(-2)
            make.right.equalTo(-22)
            make.height.equalTo(45)
        }
        lineView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(-188-TabBarMargin)
            make.width.equalTo(75)
            make.height.equalTo(1)
        }
        appleBtn.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(privacyView.snp.top).offset(-scaleWidth(100))
            make.width.equalTo(scaleWidth(240))
            make.height.equalTo(44)
        }
        fbBtn.snp.makeConstraints { make in
            make.top.equalTo(appleBtn.snp.bottom).offset(44)
            make.left.equalTo(appleBtn.snp.left).offset(44)
            make.width.height.equalTo(44)
        }
        goBtn.snp.makeConstraints { make in
            make.top.equalTo(appleBtn.snp.bottom).offset(44)
            make.right.equalTo(appleBtn.snp.right).offset(-44)
            make.width.height.equalTo(44)
        }
    }
    
    override func dataConfig() {
        pageName = "登入"
    }
}

extension WNLoginVC: UITextViewDelegate {
    
    func shakeAnimation() {
        let animation = CABasicAnimation.init(keyPath: "transform.translation.x")
        animation.duration = 0.1
        animation.fromValue = NSNumber(floatLiteral: -5)
        animation.toValue = NSNumber(floatLiteral: 5)
        animation.autoreverses = true
        agreeBtn.layer.add(animation, forKey: nil)
    }
    
    func tapLoginBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("請先閱讀並同意檢查協議")
            return
        }
        guard WNRegex(WNRegex.passwordPattern).match(input: pwStr) else {
            wn_toast("請輸入6到20個字\n至少包含1個數字和1個字母")
            return
        }
    }
    
    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        wn_pushWebVC(URL.absoluteString, URL.absoluteString == WNConfigure.WNURL.wn_Privacy ? "隱私政策" : "服務協議")
        return false
    }
}

extension WNLoginVC {
    
    /// 登录成功统一处理
    func loginSuc(_ type: String, _ model: UserDetailModel?, _ msg: String) {
        if let m = model {
            WNBuriedManager.shared.signIn(type, m.userId ?? "")
            saveUser(user: m)
            setKeyUserId(m.userId ?? "")
            WNSingleData.shared.userGold = m.gold
            wn_toast(msg)
            NotificationCenter.default.post(name: WNNotiName.loginNoti, object: self)
            dismiss(animated: true)
        }else {
            wn_toast(msg)
        }
    }
    
    /// 苹果登录
    func loginByAppleId(_ userId: String, _ openId: String) {
        WNHUD.wn_showLoading()
        provider_login.rx.request(.appleLogin(userId, openId))
            .asObservable().mapModel(BaseModel<UserDetailModel>.self)
            .subscribe(onNext: { [weak self] (model) in
                guard model.code == 0 else {
                    self?.wn_toast(model.msg ?? "")
                    return
                }
                self?.loginSuc("Apple", model.data, "登入成功")
            }, onError: { [weak self] (error) in
                self?.wn_toast("檢查網路連線")
            }).disposed(by: rx.disposeBag)
    }
    
    /// FB登录
    func loginByFacebook(_ token: String, _ userId: String, _ name: String, _ email: String, _ headUrl: String) {
        WNHUD.wn_showLoading()
        provider_login.rx.request(.facebookLogin(token, userId, name, email, headUrl))
            .asObservable().mapModel(BaseModel<UserDetailModel>.self)
            .subscribe(onNext: { [weak self] (model) in
                guard model.code == 0 else {
                    self?.wn_toast(model.msg ?? "")
                    return
                }
                self?.loginSuc("FB", model.data, "登入成功")
            }, onError: { [weak self] (error) in
                self?.wn_toast("檢查網路連線")
            }).disposed(by: rx.disposeBag)
    }
}

extension WNLoginVC {
    
    @objc func touchAppleBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("請先閱讀並同意檢查協議")
            return
        }
        let controller = ASAuthorizationController(authorizationRequests: [ ASAuthorizationAppleIDProvider().createRequest()])
        controller.delegate = self
        controller.presentationContextProvider = self
        controller.performRequests()
    }
    
    func touchFacebookBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("請先閱讀並同意檢查協議")
            return
        }
        LoginManager().logOut()
        LoginManager().logIn(permissions: ["public_profile", "email"], from: self) { [weak self] (signInResult, error) in
            guard error == nil else { return }
            guard let signInResult = signInResult else { return }
            if signInResult.isCancelled {
                self?.wn_toast("您取消了授權")
            }else {
                let userID = signInResult.token?.userID ?? ""
                Profile.loadCurrentProfile { profile, error in
                    guard error == nil else { return }
                    guard let profile = profile else { return }
                    let token = signInResult.token?.tokenString ?? ""
                    let userId = profile.userID
                    let email = profile.email ?? ""
                    let name = profile.name ?? ""
                    let avatar = profile.imageURL(forMode: .square, size: .init(width: 200, height: 200))?.absoluteString ?? ""
                    self?.loginByFacebook(token, userId, name, email, avatar)
                }
            }
        }
    }
    
    func touchGoogleBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("請先閱讀並同意檢查協議")
            return
        }
        let gidConfig = GIDConfiguration(clientID: WNConfigure.Google.clientID, serverClientID: "")
        GIDSignIn.sharedInstance.configuration = gidConfig
        GIDSignIn.sharedInstance.signIn(withPresenting: self) { [weak self] (result, error) in
            guard error == nil else { return }
            guard let user = result?.user else { return }
            let userID = user.userID ?? ""
            let email = user.profile?.email ?? ""
            let name = user.profile?.name ?? ""
            let avatar = user.profile?.imageURL(withDimension: 320)?.absoluteString ?? ""
            self?.wn_toast("userId = \(userID)\n email = \(email)\n name = \(name)\n avatar = \(avatar)", 3)
        }
    }
}

extension WNLoginVC: ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if authorization.credential is ASAuthorizationAppleIDCredential {
            let credential = authorization.credential as! ASAuthorizationAppleIDCredential
            let userId = credential.user
            guard !userId.isEmpty,
                  let idTokenData = credential.identityToken,
                  let authCodeData = credential.authorizationCode,
                  let idToken = String(data: idTokenData, encoding: .utf8), !idToken.isEmpty,
                  let authCode = String(data: authCodeData, encoding: .utf8), !authCode.isEmpty else
            {
                self.failCompletion()
                return
            }
            loginByAppleId(userId, idToken)
        }else if authorization.credential is ASPasswordCredential {
            failCompletion()
        }else {
            failCompletion("授權錯誤")
        }
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        var errMsg: String = "未知的錯誤"
        switch error {
        case ASAuthorizationError.canceled:
            errMsg = "您取消了授權"
        case ASAuthorizationError.failed:
            errMsg = "授權錯誤"
        case ASAuthorizationError.invalidResponse:
            errMsg = "授權無效"
        case ASAuthorizationError.notHandled:
            errMsg = "處理授權失敗"
        case ASAuthorizationError.unknown:
            errMsg = "未知授權"
        default:
            break
        }
        failCompletion(errMsg)
    }
    
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        if let windowOption = UIApplication.shared.delegate?.window {
            if let window = windowOption {
                return window
            }
        }
        return UIWindow(frame: Screen.bounds)
    }
    
    func failCompletion(_ str: String = "登入失敗") {
        wn_toast(str)
    }
}
